package com.test.test01.serviceImpl;


import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.test01.bean.SystemJob;
import com.test.test01.common.base.error.CommonException;
import com.test.test01.mapper.SystemJobMapper;
import com.test.test01.schedule.runnable.SchedulingRunnable;
import com.test.test01.schedule.register.CronTaskRegister;
import com.test.test01.service.SystemJobService;
import com.test.test01.utils.SpringContextUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

@Service
public class SystemJobServiceImpl extends ServiceImpl<SystemJobMapper, SystemJob> implements SystemJobService {


    @Resource
    private SystemJobService systemJobService;
    @Resource
    private CronTaskRegister cronTaskRegister;
    @Resource
    private JdbcTemplate jdbcTemplate;
    @Resource
    private TransactionTemplate transactionTemplate;


    /**
     * 分页查询系统定时任务
     *
     * @param beanName   bean名称
     * @param methodName 方法名
     * @param jobStatus  任务状态
     * @param pageNo     页号
     * @param pageSize   页面大小
     * @return
     */
    @Override
    public Page<SystemJob> pageSystemJob(String beanName, String methodName, Integer jobStatus, Integer pageNo, Integer pageSize) {
        return systemJobService.page(new Page<>(pageNo, pageSize), Wrappers.lambdaQuery(SystemJob.class)
                .eq(SystemJob::getBeanName, beanName)
                .eq(SystemJob::getMethodName, methodName)
                .eq(SystemJob::getJobStatus, jobStatus)
                .eq(SystemJob::getDeleteFlag, 0));
    }

    /**
     * 添加系统定时任务
     *
     * @param systemJob 系统定时任务
     */
    @Override
    public void addSystemJob(SystemJob systemJob) {
        //1,验证实体名,方法名,方法参数是否存在
        validateBeanAndMethod(systemJob.getBeanName(), systemJob.getMethodName(), systemJob.getMethodParams());

        //2,验证数据库是否存在传递的该参数
        SystemJob existSystemJob = systemJobService.getOne(Wrappers.lambdaQuery(SystemJob.class).eq(SystemJob::getBeanName, systemJob.getBeanName())
                .eq(SystemJob::getMethodName, systemJob.getMethodName())
                .eq(SystemJob::getMethodParams, systemJob.getMethodParams())
                .eq(SystemJob::getDeleteFlag, 0));
        if (ObjectUtil.isNotEmpty(existSystemJob)) {
            throw new CommonException("系统定时任务已存在，请勿重复添加");
        }

        //3,添加参数到数据库
        systemJobService.save(systemJob);

        //4.根据传递参数的状态进行运行定时任务
        if (ObjectUtil.equal(1, systemJob.getJobStatus())) {
            SchedulingRunnable task;
            //判断运行类型是一次还是多次
            if (ObjectUtil.equal(1, systemJob.getJobCount())) {
                task = new SchedulingRunnable(systemJob.getId(), systemJob.getBeanName(),
                        systemJob.getMethodName(), systemJob.getMethodParams(), systemJob.getJobCount(), systemJob.getCronExpression(),
                        cronTaskRegister, jdbcTemplate, transactionTemplate);
            } else {
                task = new SchedulingRunnable(systemJob.getBeanName(), systemJob.getMethodName(), systemJob.getMethodParams());
            }

            cronTaskRegister.addCronTask(task, systemJob.getCronExpression());
        }

    }

    /**
     * 修改系统定时任务
     *
     * @param systemJob 系统定时任务
     */
    @Override
    public void modifySystemJob(SystemJob systemJob) {
        //1,验证实体名,方法名,方法参数是否存在
        validateBeanAndMethod(systemJob.getBeanName(), systemJob.getMethodName(), systemJob.getMethodParams());

        //2,验证传递的任务是否存在数据库中
        SystemJob existSystemJob = systemJobService.getById(systemJob.getId());
        if (ObjectUtil.isEmpty(existSystemJob)) {
            throw new CommonException("系统定时任务不存在!");
        }

        //3,验证传递的参数是否和数据库的任务重复
        SystemJob repeatSystemJob = systemJobService.getOne(Wrappers.lambdaQuery(SystemJob.class).eq(SystemJob::getBeanName, systemJob.getBeanName())
                .eq(SystemJob::getMethodName, systemJob.getMethodName())
                .eq(SystemJob::getMethodParams, systemJob.getMethodParams())
                .eq(SystemJob::getCronExpression,systemJob.getCronExpression())
                .eq(SystemJob::getIsFinish,0)
                .eq(SystemJob::getDeleteFlag, 0));
        if (ObjectUtil.isNotEmpty(repeatSystemJob)) {
            throw new CommonException("系统定时任务已存在，请勿重复添加");
        }

        //4,修改数据库的参数
        systemJobService.updateById(systemJob);

        //5,判断原来数据库的任务是否还在运行中,在运行中则关闭
        if (ObjectUtil.equal(1, existSystemJob.getJobStatus())) {
            SchedulingRunnable task = new SchedulingRunnable(existSystemJob.getBeanName(), existSystemJob.getMethodName(), existSystemJob.getMethodParams());
            cronTaskRegister.removeCronTask(task);
        }

        //6,开启修改参数后的定时任务
        if (ObjectUtil.equal(1, systemJob.getJobStatus())) {
            SchedulingRunnable task;
            //判断运行类型是一次还是多次
            if (ObjectUtil.equal(1, systemJob.getJobCount())) {
                task = new SchedulingRunnable(systemJob.getId(), systemJob.getBeanName(),
                        systemJob.getMethodName(), systemJob.getMethodParams(), systemJob.getJobCount(), systemJob.getCronExpression(),
                        cronTaskRegister, jdbcTemplate, transactionTemplate);
            } else {
                task = new SchedulingRunnable(systemJob.getBeanName(), systemJob.getMethodName(), systemJob.getMethodParams());
            }

            cronTaskRegister.addCronTask(task, systemJob.getCronExpression());
        }

    }

    /**
     * 移除系统定时任务
     *
     * @param id 任务ID
     */
    @Override
    public void removeSystemJob(Long id) {

        //1,查询数据库的此任务是否存在
        SystemJob existSystemJob = systemJobService.getById(id);
        if (ObjectUtil.isEmpty(existSystemJob)) {
            throw new CommonException("系统定时任务不存在!");
        }

        //2,执行删除操作
        systemJobService.removeById(id);

        //3,关闭定时任务
        if (ObjectUtil.equal(1, existSystemJob.getJobStatus())) {
            SchedulingRunnable task = new SchedulingRunnable(existSystemJob.getBeanName(), existSystemJob.getMethodName(), existSystemJob.getMethodParams());
            cronTaskRegister.removeCronTask(task);
        }
    }

    /**
     * 修改定时任务状态
     *
     * @param id        任务ID
     * @param jobStatus 任务状态
     */
    @Override
    public void modifyJobStatus(Long id, Integer jobStatus) {

        //1,查询数据库的此任务是否存在
        SystemJob existSystemJob = systemJobService.getById(id);
        if (ObjectUtil.isEmpty(existSystemJob)) {
            throw new CommonException("系统定时任务不存在!");
        }

        SystemJob systemJob = new SystemJob();
        systemJob.setId(id);
        systemJob.setJobStatus(jobStatus);
        //2,修改数据库中该任务的状态
        systemJobService.updateById(systemJob);

        //3,根据传递过来的状态判断是都开启定时任务
        if (ObjectUtil.equal(1, jobStatus)) {
            SchedulingRunnable task;
            //判断运行类型是一次还是多次
            if (ObjectUtil.equal(1, existSystemJob.getJobCount())) {
                task = new SchedulingRunnable(existSystemJob.getId(), existSystemJob.getBeanName(),
                        existSystemJob.getMethodName(), existSystemJob.getMethodParams(), existSystemJob.getJobCount(), existSystemJob.getCronExpression(),
                        cronTaskRegister, jdbcTemplate, transactionTemplate);
            } else {
                task = new SchedulingRunnable(existSystemJob.getBeanName(), existSystemJob.getMethodName(), existSystemJob.getMethodParams());
            }

            cronTaskRegister.addCronTask(task, existSystemJob.getCronExpression());
        } else {
            SchedulingRunnable task = new SchedulingRunnable(existSystemJob.getBeanName(), existSystemJob.getMethodName(), existSystemJob.getMethodParams());
            cronTaskRegister.removeCronTask(task);
        }

    }

    /**
     * 获取定时任务详情
     *
     * @param id 任务ID
     * @return 定时任务详情
     */
    @Override
    public SystemJob querySystemJob(Long id) {
        return systemJobService.getById(id);
    }

    /**
     * 立即执行
     *
     * @param beanName     bean名称
     * @param methodName   方法名
     * @param methodParams 方法参数
     */
    @Override
    public void immediatelyExecute(String beanName, String methodName, String methodParams) {
        validateBeanAndMethod(beanName, methodName, methodParams);

        SchedulingRunnable.execute(beanName, methodName, methodParams);
    }

    private void validateBeanAndMethod(String beanName, String methodName, String methodParams) {
        Object target;
        try {
            target = SpringContextUtils.getBean(beanName);
        } catch (Exception e) {
            throw new CommonException("不存在的Bean");
        }

        try {
            if (StringUtils.isNotEmpty(methodParams)) {
                target.getClass().getDeclaredMethod(methodName, String.class);
            } else {
                target.getClass().getDeclaredMethod(methodName);
            }
        } catch (Exception e) {
            throw new CommonException("不存在的方法名");
        }
    }
}
